use glium::{
    implement_vertex,
    uniform,
    Display,
    Program,
    vertex::VertexBuffer,
    index::NoIndices,
    Frame,
    Surface
};

mod math;
mod context;

use context::{ App, AppListener };
use crate::math::Matrix4;

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 2],
}

implement_vertex!(Vertex, position);

macro_rules! vertices {
    ($d: expr; $($x: expr, $y: expr); +) => {
        {
            let v = vec![
                $(Vertex { position: [$x, $y] }),+
            ];

            VertexBuffer::new($d, &v).unwrap()
        }
    };
}

struct MyListener  {
    vbo: VertexBuffer<Vertex>,
    program: Program,
}

impl AppListener for MyListener {
    fn new(display: &Display) -> Self {
        let vbo = vertices![
            display;
            -0.25, -0.25;
            -0.25, 0.25;
            0.25, 0.25;
            0.25, -0.25
        ];

        let program = Program::from_source(display, include_str!("../shaders/simple.vert"), include_str!("../shaders/simple.frag"), None).unwrap();

        Self {
            vbo,
            program,
        }
    }

    fn resize(&mut self, x: f32, y: f32) {
        println!("Resized x: {}, y: {}", x, y)
    }

    fn update(&self, app: &App<Self>, gl: &mut Frame) {
        gl.clear_color(1.0, 1.0, 1.0, 1.0);
        let cp = -app.get_cursor_position();
        let u = uniform!{
            click: app.get_key_down(),
            color: [0.5, 0.2, 0.6, 1.0f32],
            // Model * View * Projection
            model: Matrix4::scale(100.0, 100.0, 1.0),
            view: Matrix4::translation(400.0, 400.0, 0.0),
            proj: Matrix4::orthogonal(0.0, 800.0, 0.0, 800.0, -100.0, 100.0)
        };
        gl.draw(&self.vbo, NoIndices(glium::index::PrimitiveType::TriangleFan), &self.program, &u, &Default::default()).unwrap();
    }
}

fn main() {
    let app: App<MyListener> = App::new();
    app.run();
}